# gui_maker.py
#
#

# 
# 
#

import sys
from Tkinter import *                     # widget classes
from types   import *                     # type constants

DEFAULT_FONT = ('Courier New', 12)
class Panel(Frame):

    def __init__(self, root = None, row = 0, column = 0, sticky = N + W, relief = GROOVE, bd = 2):
        if not root:
            root = Tk()
        Frame.__init__(self, root, relief = relief, bd = bd)
        self.grid(row = row, column = column, sticky = sticky, padx = 4, pady = 4)
        
class ItemBox(Listbox):

    def __init__(self, root = None, row = 0, column = 0, sticky = N + W, selectmode = SINGLE):

        Listbox.__init__(self, root, selectmode = selectmode)
        self.grid(row = row, column = column, sticky = sticky, padx = 2, pady = 2)
        yScroll = Scrollbar(root, orient = VERTICAL)
        yScroll.grid(row = row, column = column + 1, sticky = W + N + S, pady = 4)
        self['yscrollcommand'] = yScroll.set
        yScroll['command'] = self.yview

        
    def select_item(self, selection):

        last_sel = self.index(ACTIVE)
        self.yview_scroll(selection - last_sel, UNITS)
        self.activate(selection)
        self.selection_set(selection)

# not using set, get but trace


# only support link between StringVar and IntVar
# for Var of same type, should share a Var
def link_variables(var1, var2):
    assert type(var1) != type(var2)

    def helper(sender, reciever):
        if isinstance(sender, StringVar):
            convert = int
        else:
            convert = str
        reciever.set(convert(sender.get()))
        
    class _CallBack():
        
        def __init__(self, sender, reciever):
            self.sender = sender
            self.reciever = reciever
            

        def __call__(self, *args):
            helper(self.sender, self.reciever)
        
    var1.trace_variable('w', _CallBack(var1, var2))
    var2.trace_variable('w', _CallBack(var2, var1))
    
class BitWiseIntVar(IntVar):

    def __init__(self, total, master = None, value = 0, name = None):

        self.total = total
        self.initial_value = value
        print 'master is ', master
        IntVar.__init__(self, master, value, name)
        self.trace_variable('w', self.callback)
        
    def set(self, value):
        print 'setting %d' % value
        IntVar.set(self, value)
        if value:
            self.total.set(self.total.get() | self.initial_value)
        else:
            self.total.set(self.total.get() & ~self.initial_value)
        print 'now total is %d' % self.total.get()   

    def get(self):
        print 'current is %d' % IntVar.get(self)
        return IntVar.get(self)
    
    def callback(self, name, unknown, op_type):
        self.set(self.get())
            
class CheckGroupMaker:

    def __init__(self, root, pairs, total_val, column_num = 3):

        self.root = root
        self.pairs = pairs
        self.total_val = total_val
        self.column_num = 3
        
        self.create_checkgroup()
           
    def create_checkgroup(self):

        row = 0
        column = 0
        count = 0
        for name, onval in self.pairs:
            onval = int(onval)
            val = BitWiseIntVar(self.total_val, self.root, onval)
            val.set(0)
            btn = Checkbutton(self.root, text = name, variable = val, font = DEFAULT_FONT, onvalue = onval, offvalue = 0)   
            btn.grid(row = row, column = column, sticky = W + N, padx = 2, pady = 2)
        
            column += 1
            count += 1
            if count % self.column_num == 0:
                row += 1
                column = 0
            
        
if __name__ == '__main__':
    root = Tk()
    pairs = [('first' , 1), ('second', 10), ('third', 100)]
    total = IntVar()
    g = CheckGroupMaker(root, pairs, total)
    g.root.mainloop()
        
